﻿using System;
using System.Collections;
using System.Collections.Generic;
using Me.Prettyprint.Cassandra.Connection;
using Me.Prettyprint.Cassandra.Serializers;
using Me.Prettyprint.Cassandra.Service;
using Me.Prettyprint.Cassandra.Utils;
using Me.Prettyprint.Hector.Api;
using Me.Prettyprint.Hector.Api.Beans;
using Me.Prettyprint.Hector.Api.Query;
using Org.Apache.Cassandra.Thrift;

namespace Me.Prettyprint.Cassandra.Model
{
    /// <summary>
    /// Default implementation of HCounterSuperColumn requires the super column, super column
    /// serializer, counter columns and column name serializer.
    /// </summary>
    /// <typeparam name="SN"></typeparam>
    /// <typeparam name="N"></typeparam>
    public class HCounterSuperColumnImpl<SN, N> : HCounterSuperColumn<SN, N>
    {
        public HCounterSuperColumnImpl(SN sName, List<HCounterColumn<N>> counterColumns,
            Serializer<SN> sNameSerializer, Serializer<N> nameSerializer) : this(sNameSerializer, nameSerializer)
        {
            if (sName == null || counterColumns == null)
            {
                throw new NullReferenceException("SuperName and Columns cannot be null");
            }
            Name = sName;
            Columns = counterColumns;
        }
        public HCounterSuperColumnImpl(CounterSuperColumn thriftCounterSuperColumn, 
            Serializer<SN> sNameSerializer, Serializer<N> nameSerializer)
            : this(sNameSerializer, nameSerializer)
        {
            if (thriftCounterSuperColumn == null || sNameSerializer == null || nameSerializer == null)
            {
                throw new NullReferenceException("Serializers cannot be null");
            }
            ByteBuffer buff = new ByteBuffer(thriftCounterSuperColumn.Name);
            Name = sNameSerializer.FromByteBuffer(buff);
            Columns = FromThriftColumns(thriftCounterSuperColumn.Columns);
        }
        public HCounterSuperColumnImpl(Serializer<SN> sNameSerializer, Serializer<N> nameSerializer)
        {
            if (sNameSerializer == null || nameSerializer == null)
            {
                throw new NullReferenceException("Serializers cannot be null");
            }
            SuperNameSerializer = sNameSerializer;
            NameSerializer = nameSerializer;
        }
        public SN Name
        {
            get;
            set;
        }
        public List<HCounterColumn<N>> Columns
        {
            get;set;
        }
        public Serializer<SN> SuperNameSerializer
        {
            get;set;
        }
        protected Serializer<N> NameSerializer
        {
            get;
            set;
        }
        public int Count
        {
            get
            {
                return Columns == null ? 0 : Columns.Count;
            }
        }
        public HCounterColumn<N> Get(int i)
        {
            return Columns[i];
        }
        public HCounterSuperColumn<SN, N> AddSubCounterColumn(HCounterColumn<N> counterColumn)
        {
            if (Columns == null)
            {
                Columns = new List<HCounterColumn<N>>();
            }
            Columns.Add(counterColumn);
            return this;
        }
        public HCounterSuperColumn<SN, N> SetName(SN name)
        {
            Name = name;
            return this;
        }
        public Serializer<SN> GetNameSerializer()
        {
            return SuperNameSerializer;
        }
        public Serializer<SN> GetSuperNameSerializer()
        {
            return SuperNameSerializer;
        }
        public HCounterSuperColumn<SN, N> SetSubcolumns(List<HCounterColumn<N>> counterSubcolumns)
        {
            if (counterSubcolumns == null)
            {
                throw new NullReferenceException("Subcolumns cannot be null");
            }
            Columns = counterSubcolumns;
            return this;
        }
        private List<HCounterColumn<N>> FromThriftColumns(List<Org.Apache.Cassandra.Thrift.CounterColumn> tcolumns)
        {
            List<HCounterColumn<N>> cs = new List<HCounterColumn<N>>(tcolumns.Count);
            foreach (Org.Apache.Cassandra.Thrift.CounterColumn c in tcolumns) 
            {
                cs.Add(new HCounterColumnImpl<N>(c, NameSerializer));
            }
            return cs;
        }
        public byte[] NameBytes
        {
            get
            {
                return SuperNameSerializer.ToBytes(Name);
            }
        }

        public ByteBuffer getNameByteBuffer()
        {
            return SuperNameSerializer.ToByteBuffer(Name);
        }
        public CounterSuperColumn ToThrift()
        {
            if (Name == null || Columns == null)
            {
                return null;
            }
            CounterSuperColumn supcol = new CounterSuperColumn();
            supcol.Columns = ToThriftColumn();
            supcol.Name = SuperNameSerializer.ToBytes(Name);
            supcol.__isset.columns = true;
            supcol.__isset.name = true;
            return supcol;
        }
        private List<CounterColumn> ToThriftColumn()
        {
            List<CounterColumn> ret = new List<CounterColumn>(Columns.Count);
            foreach (HCounterColumn<N> c in Columns)
            {
                ret.Add(((HCounterColumnImpl<N>) c).ToThrift());
            }
            return ret;
        }
        public override string ToString()
        {
            return string.Format("HCounterSuperColumn({0},{1})", Name, Columns);
        }

    }
}
